package com.ztesoft.book.core.sys.sysmenu.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ztesoft.book.common.constant.Constant;
import com.ztesoft.book.common.utils.exception.ExUtil;
import com.ztesoft.book.core.base.base.service.impl.BaseExServiceImpl;
import com.ztesoft.book.core.sys.sysmenu.dto.SysMenuDTO;
import com.ztesoft.book.core.sys.sysmenu.mapper.SysMenuMapper;
import com.ztesoft.book.core.sys.sysmenu.qo.SysMenuQO;
import com.ztesoft.book.core.sys.sysmenu.service.SysMenuService;
import com.ztesoft.book.core.sys.sysrole.dto.SysRoleDTO;
import com.ztesoft.book.core.sys.sysrole.qo.SysRoleQO;
import com.ztesoft.book.core.sys.sysrole.service.SysRoleService;
import com.ztesoft.book.core.sys.sysrolemenu.dto.SysRoleMenuDTO;
import com.ztesoft.book.core.sys.sysrolemenu.mapper.SysRoleMenuMapper;
import com.ztesoft.book.core.sys.sysrolemenu.qo.SysRoleMenuQO;
import com.ztesoft.book.core.sys.sysuser.dto.SysUserDTO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * @Description 菜单业务类
 * @Author YangFan
 * @Date 2021-06-22 17:32
 */
@Service("sysMenuService")
public class SysMenuServiceImpl extends BaseExServiceImpl<SysMenuMapper, SysMenuDTO, SysMenuQO> implements SysMenuService {

    protected static final String PARENT_ID = "0";

    @Resource
    private SysMenuMapper sysMenuMapper;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysRoleMenuMapper sysRoleMenuMapper;

    @Override
    protected void beforeAdding(SysMenuDTO sysMenuDTO) {

        if (StringUtils.isBlank(sysMenuDTO.getUrl())) {
            sysMenuDTO.setUrl("");
        }

        if (StringUtils.isBlank(sysMenuDTO.getComponent())) {
            sysMenuDTO.setComponent("");
        }
    }


    /**
     * 获取页面树
     *
     * @return
     */
    @Override
    public List<SysMenuDTO> findMenuTree() {
        List<SysMenuDTO> sysMenuDTOS = this.getMapper()
                .findList(new SysMenuQO());
        Map<String, SysMenuDTO> sysMenuMap = sysMenuDTOS.stream()
                .collect(Collectors.toMap(SysMenuDTO::getId, a -> a));
        List<SysMenuDTO> list = new ArrayList<>();
        getMenuTree(list, PARENT_ID, sysMenuDTOS, sysMenuMap);
        return list;
    }

    /**
     * 获取树
     *
     * @param roleId roleId
     * @return
     */
    @Override
    public List<SysMenuDTO> findRoleMenuTree(String roleId) {
        SysUserDTO shiroUser = getShiroUser();
        String adminMerchantId = "0";
        SysRoleQO qo = new SysRoleQO();
        qo.setRoleCode(Constant.ROLE_ADMIN);
        SysRoleDTO adminRole = sysRoleService.findOne(qo);
        qo.setRoleCode(Constant.ROLE_MERCHANT_ADMIN);
        SysRoleDTO merchantAdminRole = sysRoleService.findOne(qo);
        List<SysMenuDTO> menuList;
        menuList = this.getMapper().findAdminRoleMenuList(adminRole.getId(), roleId);
        Map<String, SysMenuDTO> sysMenuMap = menuList.stream()
                .collect(Collectors.toMap(SysMenuDTO::getId, a -> a));
        List<SysMenuDTO> list = new ArrayList<>();
        getMenuTree(list, PARENT_ID, menuList, sysMenuMap);
        return list;
    }

    /**
     * 更新权限菜单
     *
     * @param qo qo
     */
    @Override
    public void updateRoleMenu(SysRoleMenuQO qo) {
        List<String> menuIds = qo.getMenuIds();
        // 补充父级id
        List<SysMenuDTO> sysMenuDTOS = sysMenuMapper.selectList(null);
        Map<String, SysMenuDTO> map = sysMenuDTOS.stream().collect(Collectors.toMap(SysMenuDTO::getId, e -> e, (k1, k2) -> k1));
        Set<String> newMenuIds = new HashSet<>();
        for (String menuId : menuIds) {
            putParentId(menuId, map, newMenuIds);
        }

        String roleId = qo.getRoleId();
        ExUtil.checkArgument(StrUtil.isNotBlank(roleId), "角色id不能为空");
        List<SysRoleMenuDTO> list = sysRoleMenuMapper.findList(qo);
        // 旧有新无
        List<String> toDeleteList = list.stream()
                .map(SysRoleMenuDTO::getMenuId)
                .filter(menuId -> !newMenuIds.contains(menuId))
                .collect(Collectors.toList());
        // 新有旧无
        List<String> toAddList = newMenuIds.stream()
                .filter(menuId -> {
                    return list.stream()
                            .map(SysRoleMenuDTO::getMenuId)
                            .noneMatch(menuId::equals);
                })
                .collect(Collectors.toList());
        if (CollUtil.isNotEmpty(toDeleteList)) {
            QueryWrapper<SysRoleMenuDTO> wrapper = new QueryWrapper<>();
            wrapper.lambda()
                    .eq(SysRoleMenuDTO::getRoleId, roleId)
                    .in(SysRoleMenuDTO::getMenuId, toDeleteList);
            sysRoleMenuMapper.delete(wrapper);
        }
        if (CollUtil.isNotEmpty(toAddList)) {
            for (String menuId : toAddList) {
                SysRoleMenuDTO sysRoleMenuDTO = new SysRoleMenuDTO();
                sysRoleMenuDTO.setRoleId(roleId);
                sysRoleMenuDTO.setMenuId(menuId);
                sysRoleMenuMapper.insert(sysRoleMenuDTO);
            }
        }
    }

    private void putParentId(String menuId, Map<String, SysMenuDTO> map, Set<String> result) {
        SysMenuDTO sysMenuDTO = map.get(menuId);
        if (sysMenuDTO != null) {
            result.add(sysMenuDTO.getId());
            putParentId(sysMenuDTO.getParentId(), map, result);
        }
    }

    /**
     * 递归获取列表
     *
     * @param list
     * @param parentId
     * @param sysMenuDTOS
     * @return
     */
    private void getMenuTree(
            List<SysMenuDTO> list, String parentId, List<SysMenuDTO> sysMenuDTOS, Map<String, SysMenuDTO> sysMenuMap) {

        //获取子类
        List<SysMenuDTO> childrenList = sysMenuDTOS.stream()
                .filter(setting -> {
                    return setting.getParentId()
                            .equals(parentId);
                })
                .collect(Collectors.toList());

        for (SysMenuDTO sysMenuDTO : childrenList) {

            List<SysMenuDTO> children = new ArrayList<>();
            getMenuTree(children, sysMenuDTO.getId(), sysMenuDTOS, sysMenuMap);
            if (!children.isEmpty()) {
                sysMenuDTO.setChildren(children);
            }
            //设置上级名
            if (sysMenuMap.containsKey(sysMenuDTO.getParentId())) {
                sysMenuDTO.setParentName(sysMenuMap.get(sysMenuDTO.getParentId())
                        .getName());

            }

            list.add(sysMenuDTO);

        }
    }


    @Override
    protected SysMenuMapper getMapper() {
        return sysMenuMapper;
    }

}
